import java.io.*;
import java.util.List;
import java.util.Map;

/**
 * 利用赫夫曼编码压缩文件
 *
 * @Author: wanqian
 * @Date: 2021/2/20 16:46
 */
public class ZipFileDemo {

    public static void main(String[] args) {
//        zipFile("C:\\Users\\Qian\\Desktop\\c1919ca75778884ac974498efb57ac4.jpg", "C:\\Users\\Qian\\Desktop\\c1919ca75778884ac974498efb57ac4.zip");
        unzipFile("C:\\Users\\Qian\\Desktop\\c1919ca75778884ac974498efb57ac4.zip", "C:\\Users\\Qian\\Desktop\\test.jpg");
    }

    /**
     * 压缩文件
     *
     * @param srcPath
     * @param targetPath
     */
    public static void zipFile(String srcPath, String targetPath) {
        try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(srcPath));
             ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(targetPath))
        ) {
            //读取文件内容
            byte[] bytes = new byte[bis.available()];
            bis.read(bytes);
            //赫夫曼压缩
            byte[] huffmanZip = HuffmanEncodeDemo.huffmanZip(bytes);
            //编码表
            Map<Byte, String> huffCodeTable = HuffmanEncodeDemo.getHuffCodeTable(bytes);
            //写入压缩数据和编码表
            oos.writeObject(huffmanZip);
            oos.writeObject(huffCodeTable);
            oos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 解压文件
     *
     * @param srcPath
     * @param targetPath
     */
    public static void unzipFile(String srcPath, String targetPath) {
        try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(srcPath));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetPath))
        ) {
            //读取文件内容
            byte[] bytes = (byte[]) ois.readObject();
            Map<Byte, String> table = (Map<Byte, String>) ois.readObject();
            //解码
            List<Byte> byteList = HuffmanDecodeDemo.decodeByte(table, bytes);
            //写入原数据
            byte[] data = new byte[byteList.size()];
            for (int i = 0; i < byteList.size(); i++) {
                data[i] = byteList.get(i);
            }
            bos.write(data);
            bos.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

}
